package com.ld.web.config;

import com.ld.web.shiro.UserRealm;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Value("${spring.redis.host}")
    private String redisHost;
    @Value("${spring.redis.port}")
    private String redisPort;
    @Value("${spring.redis.timeout}")
    private Integer redisTimeout;
    @Value("${spring.redis.password}")
    private String redisPassword;

    @Autowired
    private UserRealm userRealm;
//使用reids Session
//    @Bean(name = "sessionDAO")
//    public SessionDAO sessionDAO(){
//        return new EnterpriseCacheSessionDAO();
//    }

    /**
     *  shiro自带开源插件
     * @return
     */
    @Bean(name = "redisManager")
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();  //设置redis连接池属性
        JedisPool jedisPool = new JedisPool(jedisPoolConfig,redisHost,Integer.valueOf(redisPort),redisTimeout,redisPassword);
        redisManager.setJedisPool(jedisPool);
//        redisManager.setPassword(redisPassword);
        /*redisManager.setHost(redisHost+":"+redisPort);
        redisManager.setTimeout(redisTimeout);
        redisManager.setPassword(redisPassword);*/
//        redisManager.setPassword(redisPassword);
        return redisManager;
    }

    /**
     * shiro-redis 开源插件
     * @param redisManager
     * @return
     */
    @Bean(name = "redisSessionDAO")
    public RedisSessionDAO redisSessionDAO(@Qualifier(value = "redisManager") RedisManager redisManager){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager);
        /*RedisSerializer redisSerializer = new ObjectSerializer();
        try {
            redisSerializer.serialize(UUID.randomUUID());
        } catch (SerializationException e) {
            e.printStackTrace();
        }
        redisSessionDAO.setKeySerializer(redisSerializer);*/
        return redisSessionDAO;
    }
    /**
     * shiro-redis 开源插件
     * @param redisManager
     * @return
     */
    @Bean(name = "cacheManager")
    public RedisCacheManager cacheManager(@Qualifier(value = "redisManager") RedisManager redisManager){
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager);
        return redisCacheManager;
    }

    @Bean(name = "sessionManager")
    public SessionManager sessionManager(@Qualifier(value = "redisSessionDAO") RedisSessionDAO redisSessionDAO,@Qualifier(value = "simpleCookie") SimpleCookie simpleCookie){
        DefaultWebSessionManager manager = new DefaultWebSessionManager();
        manager.setSessionDAO(redisSessionDAO);
        manager.setGlobalSessionTimeout(3600000);
        manager.setSessionValidationInterval(3600000);
        manager.setSessionIdCookieEnabled(true);
        manager.setSessionIdCookie(simpleCookie);
        return manager;
    }

    //权限管理，配置主要是Realm的管理认证
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier(value = "sessionManager") SessionManager sessionManager,@Qualifier(value = "rememberMeManager") CookieRememberMeManager rememberMeManager
    ,@Qualifier(value = "cacheManager") RedisCacheManager cacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 自定义缓存实现 使用redis
        securityManager.setCacheManager(cacheManager);
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager);
        //注入记住我管理器;
        securityManager.setRememberMeManager(rememberMeManager);
        // 设置realm.
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier(value = "securityManager") SecurityManager securityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
     //   shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setLoginUrl("/unauth");
        //自定义拦截器
        Map<String,String> map = new HashMap<String, String>();
        //登出
        map.put("*/logout","logout");
        map.put("*/ajaxLogin", "anon");
        map.put("*/login", "anon");
        map.put("*/test/**","anon");
        map.put("*/socket/*","anon");
        map.put("*/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }


    //加入注解的使用，不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier(value = "securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    /**
     * cookie管理对象;记住我功能
     * @return
     */
    @Bean(name = "rememberMeManager")
    public CookieRememberMeManager rememberMeManager(@Qualifier(value = "simpleCookie") SimpleCookie simpleCookie){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
        cookieRememberMeManager.setCookie(simpleCookie);
        return cookieRememberMeManager;
    }

    /**
     * cookie对象;
     * @return
     */
    @Bean(name = "simpleCookie")
    public SimpleCookie simpleCookie(){
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        simpleCookie.setName("shiro-session");   //
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(2592000);
        return simpleCookie;
    }

}
